﻿#pragma once
#include "WorkerThread.h"
#include "RunnableTask.h"
#include "ThreadBody.h"
#include "Runtime/Debug/Logger.h"

namespace BattleFire
{
    class PooledThreadBody: public ThreadBody
    {
    public:
        PooledThreadBody()
            : mEnumThreadName(ENamedThreads::AnyThread)
            , mPerThreadIDTLSSlot(0xffffffff)
            , mCompositedThread(nullptr)
        {
        }
        void Setup(ENamedThreads inThreadName, uint32 InPerThreadIDTLSSlot, BattleFireAny InOwnerWorker)
        {
            mEnumThreadName = inThreadName;
            mPerThreadIDTLSSlot = InPerThreadIDTLSSlot;
            mCompositedThread = InOwnerWorker;
        }

        // Calls meant to be called from "this thread".

        /** A one-time call to set the TLS entry for this thread. **/
        void InitializeForCurrentThread()
        {
            FPlatformTLS::SetTlsValue(mPerThreadIDTLSSlot,mCompositedThread);
        }

        /** Return the index of this thread. **/
        ENamedThreads GetThreadName() const
        {
            return mEnumThreadName;
        }
        virtual void ProcessTasksUntilQuit(int32 QueueIndex) = 0;
        virtual uint64 ProcessTasksUntilIdle(int32 QueueIndex)
        {
            return 0;
        }
        virtual void EnqueueFromThisThread(int32 QueueIndex, RunnableTask* Task)
        {
            Debug("PooledThreadBody EnqueueFromThisThread %d %p",QueueIndex,Task);
        }
        virtual void RequestQuit(int32 QueueIndex) = 0;
        virtual bool EnqueueFromOtherThread(int32 QueueIndex, RunnableTask* Task)
        {
            return false;
        }
        virtual void WakeUp(int32 QueueIndex = 0) = 0;
        virtual bool IsProcessingTasks(int32 QueueIndex) = 0;
        virtual void Tick()
        {
            ProcessTasksUntilIdle(0);
        }
        virtual bool Init() override
        {
            InitializeForCurrentThread();
            return true;
        }
        virtual uint32 Run() override
        {
            Debug("PooledThreadBody Run : %d 0",mEnumThreadName);
            ProcessTasksUntilQuit(0);
            Debug("PooledThreadBody Run : %d 1",mEnumThreadName);
            //FMemory::ClearAndDisableTLSCachesOnCurrentThread();
            return 0;
        }
        virtual void Stop() override
        {
            RequestQuit(-1);
        }
        virtual void Exit() override
        {
            Debug("Thread Exit : %d",mEnumThreadName);
        }
    protected:
        ENamedThreads										mEnumThreadName;
        BattleFireUInt32									mPerThreadIDTLSSlot;
        FThreadSafeCounter									IsStalled;
        /** Array of tasks for this task thread. */
        std::vector<RunnableTask*> NewTasks;
        BattleFireAny mCompositedThread;
    };
}
